﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using CodeGen.TS.Input.XmlConfig;

namespace CodeGen.TS.Output
{
    public static class OutputWriter
    {
        const string RegionSeparator = "?#";

        public static string GenerateCode(IEnumerable<CodeGen.TS.Generation.ICodeGenerator> generators, string modulNameToGenerate)
        {
            string output;
            if (modulNameToGenerate != null)
            {
                output = "module " + modulNameToGenerate + "{ ";
            }
            else
                output = "";
            foreach (var generator in generators)
            {
                output = output + Environment.NewLine + generator.GenerateOutput();
            }

            output = output + Environment.NewLine +(modulNameToGenerate==null?"": "}");
            return output;
        }

        public static void WriteCode(string outputLocation, string code, bool containsKnockoutCode)
        {

            if (!string.IsNullOrEmpty(Properties.Settings.Default.Disclaimer))
                code = Properties.Settings.Default.Disclaimer + Environment.NewLine + Environment.NewLine + code;


            if (!outputLocation.Contains(RegionSeparator) )//Invalid path character, used for specifing a region in which the code is inserted. 
            //Then the generator shall only replace the specified region
            {
                if (containsKnockoutCode && !string.IsNullOrEmpty(Properties.Settings.Default.KnockoutReference))
                    code = Properties.Settings.Default.KnockoutReference + Environment.NewLine + Environment.NewLine + code;


                File.WriteAllText(outputLocation, code);
            }
            else
            {
                string fileName = outputLocation.Substring(0, outputLocation.IndexOf(RegionSeparator));
                if (!System.IO.File.Exists(fileName))//File does not exist yet, we can overwrite the whole file
                {
                    WriteCode(fileName, code, containsKnockoutCode);
                    return;
                }
                string regionName = outputLocation.Substring(outputLocation.IndexOf(RegionSeparator) + RegionSeparator.Length);
                if (regionName.Contains("\'"))
                {
                    regionName = regionName.Replace("\'", "\"");
                }

                var stream = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                string content;
                {
                    var reader = new StreamReader(stream);

                    stream.Position = 0;
                    content = reader.ReadToEnd();
                }
                int regionPosition;
                string regionStartString = "//#region " + regionName;
                regionPosition = content.IndexOf(regionStartString);

                if (regionPosition == -1)//Quite a primitive implementation but should work :)
                {
                    regionStartString = "#region " + regionName + "";
                    regionPosition = content.IndexOf(regionStartString);
                }
                if (regionPosition == -1)
                {
                    regionStartString = "//#region \"" + regionName + "\"";
                    regionPosition = content.IndexOf(regionStartString);
                }
                if (regionPosition == -1)
                {
                    regionStartString = "#region \"" + regionName + "\"";
                    regionPosition = content.IndexOf(regionStartString);

                }
                if (regionPosition == -1)
                {
                    regionStartString = "//#region \'" + regionName + "\'";
                    regionPosition = content.IndexOf(regionStartString);
                }
                if (regionPosition == -1)
                {
                    regionStartString = "#region \'" + regionName + "\'";
                    regionPosition = content.IndexOf(regionStartString);
                }
                if (regionPosition == -1)
                {
                    Logger.LogWarning("Region \"{0}\" not found in file \"{1}\". No code will be generated", regionName, fileName);
                    return;
                }
                string endregionString = "//#endregion";
                int endregionIndex = content.IndexOf(endregionString, regionPosition);
                if (endregionIndex == -1)
                {
                    endregionString = "#endregion";
                    endregionIndex = content.IndexOf(endregionString, regionPosition);
                }
                if (endregionIndex == -1)
                {
                    Logger.LogWarning("#endregion of region \"{0}\" not found in file \"{1}\". No code will be generated", regionName, fileName);
                    return;
                }

                string beforeContent = content.Substring(0, regionPosition);

                if (containsKnockoutCode && !string.IsNullOrEmpty(Properties.Settings.Default.KnockoutReference) && !beforeContent.Contains(Properties.Settings.Default.KnockoutReference))
                {
                    beforeContent = Properties.Settings.Default.KnockoutReference + Environment.NewLine + beforeContent;
                }
                string endContent = content.Substring(endregionIndex + endregionString.Length);
                string regionContent = regionStartString + Environment.NewLine + code + Environment.NewLine + endregionString;

                stream.Position = 0;
                stream.Close();


                string newContent = beforeContent + regionContent + endContent;
                System.IO.File.WriteAllText(fileName, newContent);


            }
        }
    }
}
